1 : <?php
2 : /*--------------------------------------------------------------------------+
3 : This file is part of eStudy.
4 : news/classes/class.NewsCategoryWordPress.inc.php
5 : - Modulgruppe: News
6 : - Beschreibung: Klasse für die News-Kategorie WordPress.
7 : - Version: 1.1.2.1, 26/01/08
8 : - Autor(en): Corinna Kropf <corinna.kropf@mni.fh-giessen.de>
9 : +---------------------------------------------------------------------------+
10 : This program is free software; you can redistribute it and/or
11 : modify it under the terms of the GNU General Public License
12 : as published by the Free Software Foundation; either version 2
13 : of the License, or any later version.
14 : +---------------------------------------------------------------------------+
15 : This program is distributed in the hope that it will be useful,
16 : but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : GNU General Public License for more details.
19 : You should have received a copy of the GNU General Public License
20 : along with this program; if not, write to the Free Software
21 : Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 : +--------------------------------------------------------------------------*/
23 :
24 1 : require_once 'class.toolspage.inc.php';
25 1 : require_once 'class.wordpressinfo.inc.php';
26 1 : require_once ("class.newscategory.inc.php");
27 :
28 : /**
29 : * Klasse für die News-Kategorie WordPress.
30 : * @package eStudy.News
31 : * @version 1.1.2.1, 26/01/08
32 : * @author Corinna Kropf <corinna.kropf@mni.fh-giessen.de>
33 : */
34 1 : class NewsCategoryWordPress extends NewsCategory
35 : {
36 : /**
37 : * Cache Objekt zur Abfrage von Modulinstallationen (Performance Tweak)
38 : * @var array
39 : */
40 : private $installCacheObject;
41 : /**
42 : * Enthaelt alle IDs der neuen und modifizierten Blogposts
43 : *
44 : * @var Array
45 : */
46 : private $handledBlogs;
47 :
48 : /**
49 : * Flag fuer die Anzeige der News-Eintraege
50 : * @var bool
51 : */
52 : private $dark;
53 : /**
54 : * HTML-Template
55 : * @var Template
56 : */
57 : private $newsTemplate;
58 : /**
59 : * Konstruktor
60 : */
61 : public function __construct($catID, $courses, $userId, $categorySettings = null, $cacheObject = null)
62 : {
63 0 : parent::__construct($catID, $courses, $categorySettings);
64 0 : $this->installCacheObject = $cacheObject;
65 0 : $this->userID = $userId;
66 0 : $this->newsTemplate = new Template(PATH_TO_ROOT."news/templates/newsarticle.html");
67 0 : }
68 : /**
69 : * Überschreibt die Methode der Oberklasse,
70 : * um weitere Initialisierungen vor der Ausgabe zu machen.
71 : * @see NewsCategory
72 : */
73 : public function echoNews($courseID, $usergroup = null)
74 : {
75 0 : $this->dark = false;
76 0 : parent::echoNews($courseID, $usergroup);
77 0 : }
78 : /**
79 : * Muss angepasst werden, falls Modulgruppen umbenannt werden!
80 : *
81 : * @see NewsCategory
82 : */
83 : public function isInstalled($courseID)
84 : {
85 0 : return Utilities::isInstalled("externaltools", $courseID, $this->installCacheObject);
86 : }
87 : /**
88 : * @see NewsCategory
89 : */
90 : public function canSelectPeriod() {
91 0 : return true;
92 : }
93 : /**
94 : * @see NewsCategory
95 : */
96 : public function getNewsHeaderTitle($courseID = null, $type = null) {
97 0 : if ( $this->news !== null && isset($this->news["count"]) ) {
98 0 : $newsCount = $this->news["count"];
99 0 : if ($newsCount > 1) $title = sprintf( $this->translate->_("%1\$s neue WordPress-Blogbeiträge"), $newsCount);
100 0 : else $title = $this->translate->_("1 neuer WordPress-Blogbeitrag");
101 0 : } else {
102 0 : $title = $this->translate->_("Keine neuen WordPress-Blogeinträge");
103 : }
104 :
105 0 : return $title;
106 : }
107 :
108 : private function getHandledBlogsSet() {
109 0 : $sqlList = "";
110 0 : foreach( $this->handledBlogs as $id ) {
111 0 : $sqlList .= $id . ",";
112 0 : }
113 0 : $sqlList .= "-99999"; // dummy wert, um das nachgestellte komma zu ignorieren
114 0 : return $sqlList;
115 : }
116 :
117 : private function getEstudyBlogUserById( $wp, $wordpressUserId ) {
118 0 : $id = Data::toMysql( $wordpressUserId, false );
119 0 : $wpUsersSQL = "SELECT user_login FROM wp_users WHERE id = '$id'";
120 0 : $login = $wp->toolDB->get_var( $wpUsersSQL );
121 0 : return $this->getEstudyBlogUser( $login );
122 : }
123 :
124 : private function getEstudyBlogUser( $login ) {
125 0 : global $db;
126 :
127 0 : $login = Data::toMysql( $login, false );
128 :
129 0 : $sql = "SELECT * FROM et_userlogindata AS et, user AS u
130 0 : WHERE et.userid = u.id AND et.login = '$login'";
131 0 : $userData = $db->get_row($sql, ARRAY_A);
132 0 : if ( $db->num_rows === 0 ) {
133 0 : return null;
134 : }
135 0 : return $userData;
136 : }
137 :
138 : private function isBlogUserNotInCourse( $courseID, $userData ) {
139 0 : global $db;
140 :
141 0 : $userInCourseSQL = "SELECT * FROM user_course
142 0 : WHERE courseID = '$courseID'
143 0 : AND userID = '".Data::toMysql( $userData['ID'], false )."'";
144 0 : $userInCourse = $db->get_row( $userInCourseSQL );
145 0 : if ( $db->num_rows === 0 && $courseID > 0 ) {
146 0 : return true;
147 : }
148 0 : return false;
149 : }
150 :
151 : private function loadComments( $wp, $userID, $time, $post ) {
152 0 : $newComSQL = "SELECT * FROM wp_{$userID}_comments
153 0 : WHERE comment_date >= '$time'
154 : AND comment_approved = '1'
155 0 : AND comment_post_ID = '".Data::toMysql($post['ID'],false)."'
156 0 : ORDER BY comment_date DESC";
157 0 : $newCom = (array) $wp->toolDB->get_results( $newComSQL, ARRAY_A );
158 0 : foreach ( $newCom as &$com ) {
159 0 : $userData = $this->getEstudyBlogUserById( $wp, $com['user_id'] );
160 0 : $this->users[$userData['ID']] = $userData;
161 0 : $com['estudy_user_id'] = $userData['ID'];
162 0 : }
163 0 : unset($com);
164 0 : $post['comment_data'] = $newCom;
165 :
166 0 : return $post;
167 : }
168 :
169 : private function markPostAsModified( $post ) {
170 0 : $postDate = strtotime( $post['post_date'] );
171 0 : $modifiedDate = strtotime( $post['post_modified'] );
172 0 : if ( $postDate < $modifiedDate ) {
173 0 : $post['post_was_modified'] = true;
174 0 : }
175 :
176 0 : return $post;
177 : }
178 :
179 : function mysqlToUnixTime($str) {
180 0 : list($date, $time) = explode(' ', $str);
181 0 : list($year, $month, $day) = explode('-', $date);
182 0 : list($hour, $minute, $second) = explode(':', $time);
183 :
184 0 : $timestamp = mktime($hour, $minute, $second, $month, $day, $year);
185 :
186 0 : return $timestamp;
187 : }
188 :
189 : /**
190 : * @see NewsCategory
191 : */
192 : protected function getNewsByPeriod($courseID, $from, $to, $lastvisit, $usergroup = null) {
193 : // Temporaerer Performance Fix: Im Foyer als Admin dauert das Laden der Seite
194 : // sonst viel zu lange ...
195 0 : if ( isset($_SESSION['course']) && $_SESSION['course'] == 0 ) return null;
196 :
197 0 : $this->news = array();
198 0 : $this->handledBlogs = array();
199 : /*
200 : * Wordpress erfordert es, dass ein Blogautor die Kommentare zu seinem
201 : * Blog freischalten muss. Das Freischaltedatum wird dabei nicht
202 : * gespeichert. Das heisst also, dass einige eStudy Nutzer Kommentare
203 : * nicht in den News angezeigt bekommen. Denn wenn der Kommentar
204 : * abgegeben wurde, er aber noch nicht freigeschaltet ist, dann wird
205 : * er nicht angezeigt. Logt sich ein eStudy Nutzer ein, ist der
206 : * Wert von $lastvisit noch kleiner als der des Kommentardatums. Beim
207 : * naechsten Login ist er groesser, daher kann der Kommentar auch nicht
208 : * mehr angezeigt werden:
209 : * 1. Nutzer logt sich ein
210 : * 2. kommentar >= $lastvisit, aber comment_approved=0 -> keine Anzeige
211 : * 3. Nutzer logt aus
212 : * 4. Kommentar wird freigeschaltet
213 : * 5. Nutzer logt sich wieder ein
214 : * 6. kommentar < $lastvisit, comment_approved=1 -> Wieder keine Anzeige
215 : */
216 0 : if (isset($courseID) && isset($lastvisit)) {
217 : // Verbindung zur Wordpress-Datenbank aufbauen
218 0 : $tools = new ToolsPage( $courseID );
219 0 : foreach ( $tools->toolsList as $tool ) {
220 0 : if ( $tool->type == 'wordpress 2' ) {
221 0 : $wp = $tool->tools['wordpress 2'];
222 0 : $wp->connectToDB();
223 0 : if ( $wp->toolDB === null ) {
224 0 : return null;
225 : }
226 0 : }
227 0 : }
228 :
229 0 : if ( ! isset($wp) ) {
230 : // Wordpress konnte nicht gefunden werden
231 0 : return null;
232 : }
233 :
234 0 : global $db;
235 : /*
236 : * Performance Tweak: Da die Wordpress News Abfrage unsäglich lahm ist, werden
237 : * die Update-Zeiten der Wordpress-User Tabellen überprüft. Nur wenn eine dieser
238 : * Tabellen upgedated wurde, werden Wordpress News gesammelt.
239 : *
240 : * Hinweis: Nicht alle DB Engines von Mysql geben das Statusfeld Update_time zurück.
241 : * In diesem Fall ist dieser Performance Tweak unmöglich. Langfristig bedarf
242 : * das DB Schema der Wordpress Blogs eine Umstrukturierung.
243 : */
244 0 : $fromTimeUnix = $this->getPeriod($courseID, $from);
245 0 : $affectedBlogIDs = array();
246 : // Posts
247 0 : $newPosts = false;
248 0 : $res = $wp->toolDB->get_results("SHOW TABLE STATUS LIKE '%_posts'");
249 0 : if ($res != null) {
250 0 : foreach ($res as $tableStatus) {
251 0 : if ($tableStatus->Update_time != null && $tableStatus->Update_time > 0) {
252 0 : $tableTimeStamp = $this->mysqlToUnixTime($tableStatus->Update_time);
253 0 : if ($tableTimeStamp >= $fromTimeUnix) {
254 0 : $newPosts = true;
255 0 : $tableName = $tableStatus->Name;
256 0 : $blogID = str_replace("wp_", "", $tableName);
257 0 : $blogID = str_replace("_posts", "", $blogID);
258 0 : $affectedBlogIDs["$blogID"] = data::toMysql($blogID);
259 : //echo "bogid: $blogID ";
260 0 : }
261 0 : }
262 0 : }
263 0 : }
264 : // Kommentare
265 0 : $newComments = false;
266 0 : $res = $wp->toolDB->get_results("SHOW TABLE STATUS LIKE '%_comments'");
267 0 : if ($res != null) {
268 : //$timeFrom = $this->getPeriod($courseID, $from); // todo: Zeit einstellbar
269 0 : foreach ($res as $tableStatus) {
270 0 : if ($tableStatus->Update_time != null && $tableStatus->Update_time > 0) {
271 0 : $tableTimeStamp = $this->mysqlToUnixTime($tableStatus->Update_time);
272 0 : if ($tableTimeStamp >= $fromTimeUnix) {
273 0 : $newComments = true;
274 0 : $tableName = $tableStatus->Name;
275 0 : $blogID = str_replace("wp_", "", $tableName);
276 0 : $blogID = str_replace("_comments", "", $blogID);
277 0 : $affectedBlogIDs["$blogID"] = data::toMysql($blogID);
278 : //echo "bogid: $blogID ";
279 0 : }
280 0 : }
281 0 : }
282 0 : }
283 :
284 : // Falls sich die Tabellen mit den Kommentaren nicht geändert haben gibt es keine neuen Wordpress News
285 0 : if (!$newPosts && !$newComments)
286 0 : return null;
287 :
288 0 : $time = Data::toMysql( date("Y-m-d H:i:s", $this->getPeriod($courseID, $lastvisit)), false );
289 0 : $courseID = Data::toMysql( $courseID );
290 0 : $slug = ($courseID) ? "kurs$courseID" : "estudy";
291 :
292 : $wpUsersSQL = "SELECT u.id AS userid, u.display_name, u.user_login, m.meta_value AS id
293 : FROM wp_users AS u, wp_usermeta AS m
294 : WHERE u.id = m.user_id AND m.meta_key = 'primary_blog'
295 0 : AND u.id IN (".implode(",", $affectedBlogIDs) .")";
296 0 : $wpUsers = $wp->toolDB->get_results( $wpUsersSQL );
297 0 : $this->news["count"] = 0;
298 0 : if ($wpUsers == null)
299 0 : return null;
300 0 : foreach ( $wpUsers as $wpUser ) {
301 : // TODO: refactor me! $userID muss eigentlich $blogID heissen!
302 0 : $userID = Data::toMysql( $wpUser->id, false );
303 0 : $login = Data::toMysql( $wpUser->user_login, false );
304 0 : $blogExists = $wp->toolDB->query("SHOW TABLE STATUS LIKE 'wp_{$userID}_posts';");
305 0 : if ( $blogExists ) {
306 0 : $newPostsSQL = "SELECT * FROM wp_{$userID}_posts AS p,
307 0 : wp_{$userID}_terms AS t,
308 0 : wp_{$userID}_term_relationships AS r,
309 0 : wp_{$userID}_term_taxonomy AS x
310 : WHERE p.id = r.object_id
311 : AND x.term_taxonomy_id = r.term_taxonomy_id
312 : AND x.term_id = t.term_id
313 0 : AND (p.post_date >= '$time' OR p.post_modified >= '$time')
314 0 : AND t.slug = '$slug'
315 : AND p.post_status = 'publish'
316 0 : ORDER BY p.post_date DESC";
317 0 : $newPosts = $wp->toolDB->get_results( $newPostsSQL, ARRAY_A );
318 0 : $count = $wp->toolDB->num_rows;
319 :
320 0 : if ( $newPosts !== null ) {
321 0 : $userData = $this->getEstudyBlogUser( $login );
322 0 : if ( $userData === null ) {
323 0 : continue;
324 : }
325 :
326 0 : if ( $this->isBlogUserNotInCourse($courseID, $userData) ) {
327 0 : continue;
328 : }
329 :
330 0 : foreach( $newPosts as &$post ) {
331 0 : $this->handledBlogs[] = $post['ID'];
332 0 : $post['estudy_user_id'] = $userData['ID'];
333 0 : if ( $post['comment_count'] > 0 ) {
334 0 : $post = $this->loadComments( $wp, $userID, $time, $post );
335 0 : }
336 0 : $post = $this->markPostAsModified( $post );
337 0 : }
338 0 : unset($post);
339 0 : $this->news["data"][] = $newPosts;
340 0 : $this->news["count"] += $count;
341 0 : $this->users[$userData['ID']] = $userData;
342 :
343 0 : } else {
344 : // Pruefen, ob es neue Kommentare gibt, die zu einem
345 : // bereits bestehenden Blogpost hinzugefuegt wurden
346 :
347 0 : $userData = $this->getEstudyBlogUser( $login );
348 0 : if ( $userData === null ) {
349 0 : continue;
350 : }
351 :
352 0 : if ( $this->isBlogUserNotInCourse($courseID, $userData) ) {
353 0 : continue;
354 : }
355 :
356 0 : $newCommentsSQL = "SELECT * FROM wp_{$userID}_comments AS c
357 0 : WHERE c.comment_date >= '$time'
358 : AND c.comment_approved = '1'
359 0 : AND c.comment_post_ID NOT IN (".
360 0 : Data::toMysql($this->getHandledBlogsSet(),false).")
361 0 : ORDER BY c.comment_date DESC";
362 0 : $newComments = $wp->toolDB->get_results( $newCommentsSQL, ARRAY_A );
363 0 : $count = $wp->toolDB->num_rows;
364 :
365 0 : if ( $newComments !== null ) {
366 0 : $blogs = array();
367 0 : foreach ( $newComments as $comment ) {
368 0 : $postId = Data::toMysql($comment['comment_post_ID'], false);
369 :
370 0 : if ( ! isset($blogs[$postId]) ) {
371 0 : $postSQL = "SELECT * FROM wp_{$userID}_posts AS p,
372 0 : wp_{$userID}_terms AS t,
373 0 : wp_{$userID}_term_relationships AS r,
374 0 : wp_{$userID}_term_taxonomy AS x
375 : WHERE p.id = r.object_id
376 : AND x.term_taxonomy_id = r.term_taxonomy_id
377 : AND x.term_id = t.term_id
378 0 : AND t.slug = '$slug'
379 : AND p.post_status = 'publish'
380 0 : AND p.id = '$postId'";
381 :
382 0 : $post = $wp->toolDB->get_row( $postSQL, ARRAY_A );
383 0 : if ( $post === null ) continue;
384 0 : $blogs[$postId] = $post;
385 0 : $userData = $this->getEstudyBlogUserById( $wp, $post['post_author'] );
386 0 : $blogs[$postId]['estudy_user_id'] = $userData['ID'];
387 0 : $this->users[$userData['ID']] = $userData;
388 0 : }
389 0 : if ( ! isset($blogs[$postId]['comment_data']) ) {
390 0 : $blogs[$postId]['comment_data'] = array();
391 0 : }
392 0 : $userData = $this->getEstudyBlogUserById( $wp, $comment['user_id'] );
393 0 : $comment['estudy_user_id'] = $userData['ID'];
394 0 : $this->users[$userData['ID']] = $userData;
395 0 : $blogs[$postId]['comment_data'][] = $comment;
396 0 : }
397 0 : if ( count($blogs) > 0 ) {
398 0 : $this->news["data"][] = $blogs;
399 0 : $this->news["count"] += $count;
400 0 : }
401 0 : }
402 : }
403 0 : }
404 0 : }
405 :
406 0 : if ( ! isset($this->news["data"]) ) $this->news = null;
407 0 : }
408 :
409 0 : return $this->news;
410 : }
411 : /**
412 : * @see NewsCategory
413 : */
414 : protected function echoNewsEntry($entry, $courseID, $usergroup = null)
415 : {
416 0 : if(!isset($this->dark) || !isset($entry)) return;
417 :
418 0 : foreach( $entry as $blog ) {
419 0 : $topic = Data::toHTML($blog["post_title"], false);
420 0 : $teaser = Data::toHTML( Utilities::chopText(strip_tags($blog["post_content"])), false);
421 0 : $author = $this->getProfileLink( $this->users, $blog['estudy_user_id'], $courseID);
422 0 : $datetime = Output::echoDate("d.m.Y H:i", $blog["post_date"]);
423 0 : $linkToArticle = Data::toHTML($blog["guid"], false);
424 0 : $modified = "";
425 0 : if ( isset($blog['post_was_modified']) ) {
426 : $modified = " <span style='font-style: italic'>("
427 0 : . $this->translate_("hat den Beitrag editiert")
428 0 : . ")</span>";
429 0 : }
430 :
431 0 : echo "<tr><td colspan='2' class='tableCellHead'>";
432 0 : echo "<a href='$linkToArticle'>$topic</a>";
433 0 : echo "</td></tr><tr><td class='tableCellDark' style='padding-left:30px'>$author$modified</td><td class='tableCellDark' style='text-align:right'>$datetime";
434 0 : echo "</td></tr>";
435 0 : if ( isset($blog['comment_data']) ) {
436 0 : if ( ! isset($blog['comment_only']) ) {
437 0 : echo "<tr><td>$teaser (<a href='$linkToArticle'>Lesen</a>)</td></tr>";
438 0 : }
439 :
440 0 : foreach ( $blog['comment_data'] as $comment ) {
441 0 : $linkToArticle = Data::toHTML($blog["guid"] . "#comment-" . $comment['comment_ID'], false );
442 0 : $teaser = Data::toHTML( Utilities::chopText(strip_tags($comment["comment_content"])), false);
443 0 : $datetime = Output::echoDate("d.m.Y H:i", $comment["comment_date"]);
444 0 : $author = $this->getProfileLink( $this->users, $comment['estudy_user_id'], $courseID);
445 0 : echo "<tr><td class='tableCellDark' style='padding-left:30px'>$author</td><td class='tableCellDark' style='text-align:right'>$datetime</td></tr>";
446 0 : echo "<tr><td>$teaser (<a href='$linkToArticle'>"
447 0 : . $this->translate->_("Lesen")
448 0 : . "</a>)</td></tr>";
449 0 : }
450 0 : } else {
451 0 : echo "<tr><td>$teaser (<a href='$linkToArticle'>"
452 0 : . $this->translate->_("Lesen")
453 0 : . "</a>)</td></tr>";
454 : }
455 0 : }
456 0 : }
457 : }
|